interface Bar {
  /**
   * 加载条开始滚动
   */
  start(): void;
  /**
   * 加载条结束滚动
   * @param duration - 长度加载完毕的延迟时间(可选，默认.25s)
   */
  finsh(duration?: number): void;
  /**
   * 卸载该组件
   */
  unMount(): void
}

class LoadingBar implements Bar {
  private instance: HTMLDivElement;
  // 定时器
  private timing: number = 0;

  constructor() {
    this.instance = document.createElement('div');
    this.instance.style.cssText += `
    position: fixed;
    top: 0;
    height: 2px;
    box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
    `;
  }

  /**
   * 改变加载条元素的样式
   * @param sty - css样式属性
   * @param value - 对应的属性值
   */
  private handleToSty(sty: string, value: string): void {
    (this.instance.style as any)[sty] = value;
  }

  start() {
    // 将加载条背景颜色变回原色
    this.handleToSty("backgroundColor", "#ffd90f");
    this.handleToSty("width", '0px');
    // 加载条在固定时间戳下增加的宽度值
    let wid: number = 0;
    document.body.append(this.instance);
    this.timing = window.setInterval(() => {
      let bodyWid: number = document.body.clientWidth; // body的宽度(最终加载条需要加载到该宽度)
      let loadingWid: number = +this.instance.style.width.replace("px", ""); // 加载条此时的宽度

      if (loadingWid <= bodyWid * 0.3) wid += 5;
      else if (
        loadingWid > bodyWid * 0.3 &&
        loadingWid <= bodyWid * 0.5
      )
        wid += 4;
      else if (
        loadingWid > bodyWid * 0.5 &&
        loadingWid <= bodyWid * 0.6
      )
        // 当加载条长度超过body宽度一半且还没完成加载时时加载速度减慢
        wid += 3;
      else if (
        loadingWid > bodyWid * 0.6 &&
        loadingWid <= bodyWid * 0.7
      )
        // 当加载条长度超过body宽度0.6倍且还没完成加载时加载速度减慢
        wid += 2;
      else if (
        loadingWid > bodyWid * 0.7 &&
        loadingWid <= bodyWid * 0.8
      )
        wid += 1;
      else if (loadingWid > bodyWid * 0.8) {
        // 当加载条长度超过body宽度0.8倍且还没完成加载时加载条背景色变红
        this.handleToSty("backgroundColor", "red");
        wid += 0.5;
      }
      // 显示此时加载条的宽度
      this.handleToSty("width", `${wid}px`);
      if (loadingWid >= bodyWid * 0.92)
        // 当加载条长度超过body宽度0.9倍且还没完成加载时不再改变宽度且15秒后重定向到404页面
        clearInterval(this.timing);
    }, 20);
  }

  finsh(duration: number = 250): void {
    this.handleToSty("transition", "width .25s linear");
    clearInterval(this.timing);
    const width: number = document.body.clientWidth;
    this.handleToSty("width", `${width}px`);
    setTimeout(() => {
      if (document.body.contains(this.instance)) {
        this.handleToSty("transition", "");
        document.body.removeChild(this.instance);
      }
    }, duration);
  }

  unMount(): void {
    clearInterval(this.timing);
    if (document.body.contains(this.instance))
      document.body.removeChild(this.instance);
  }
}

export default LoadingBar